﻿using System;
using System.Drawing;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace DirectX_CS
{
public class AnimatedPolarWaveform	: PolarWaveform, IAnimated
{
	[PGBrowsable]
	public PolarWaveform Surface0
	{
		get { return this; }
	}
    //protected PolarWaveForm mSurface1 = null;

	protected double mTime = 0;
	[PGBrowsable]
	public double Time
	{
		get { return mTime; }
		set { mTime = value; }
	}
    protected double mRestartTime = 0;

	[PGBrowsable]
	public double RestartTime
    {
        get { return mRestartTime; }
        set { mRestartTime = value; }
    }

    protected double mTimeScaleDelta = .1;
	[PGBrowsable]
    public double TimePerFrame
    {
        get { return mTimeScaleDelta; }
        set { mTimeScaleDelta = value; }
    }
    //double mFramesSinceNewData = 0;
    private double mFramesSinceLastDataChange = 0;
    private int mFramesPerChange = 1;
	[PGBrowsable]
    public int FramesPerChange
    {
        get { return mFramesPerChange; }
        set { if(value > 0)
			mFramesPerChange = value; 
		}
    }

	protected double timeMaxToReset = 20; //try using double.MaxValue -1;
	[PGBrowsable]
	public double TimeMaxToReset
	{
		get { return timeMaxToReset; }
		set { timeMaxToReset = value; }
	}

 	protected bool autoCalculateOptions = true;
	[PGBrowsable]
	public bool AutoCalculateOptions
	{
		get { return autoCalculateOptions; }
		set { autoCalculateOptions = value; }
	}

	//protected bool drawOuterLimitsCircle = true;
	//public bool DrawOuterLimitsCircle
	//{
	//    get { return drawOuterLimitsCircle; }
	//    set { drawOuterLimitsCircle = value; }
	//}
	//protected Color outerLimitsCircleColor = System.Drawing.Color.DarkBlue;

	//public Color OuterLimitsCircleColor
	//{
	//    get { return mOuterLimitsCircle.MainVertexColor; }
	//    set { mOuterLimitsCircle.MainVertexColor = value; }
	//}


    //protected Simple3dCircle mOuterLimitsCircle = null;
    //Simple3dCircle[] mCircleArray = null;

    protected double init_TMax = 2 * Math.PI;
	[PGBrowsable]
	public double Init_TMax
	{
		get { return init_TMax; }
		set { init_TMax = value; }
	}
    protected double init_TMin = 0;
	[PGBrowsable]
	public double Init_TMin
	{
		get { return init_TMin; }
		set { init_TMin = value; }
	}
    protected double init_RMin = 0;
	[PGBrowsable]
	public double Init_RMin
	{
		get { return init_RMin; }
		set { init_RMin = value; }
	}
    protected double init_RMax = 0;
	[PGBrowsable]
	public double Init_RMax
	{
		get { return init_RMax; }
		set { init_RMax = value; }
	}
    protected double init_AngleMin = 0;
	[PGBrowsable]
	public double Init_AngleMin
	{
		get { return init_AngleMin; }
		set { init_AngleMin = value; }
	}
    protected double init_AngleMax = 2 * Math.PI;
	[PGBrowsable]
	public double Init_AngleMax
	{
		get { return init_AngleMax; }
		set { init_AngleMax = value; }
	}
	protected int init_AngleDivisions = 30;
	[PGBrowsable]
	public int Init_AngleDivisions
	{
		get { return init_AngleDivisions; }
		set { init_AngleDivisions = value; }
	}
    protected int init_RadialDivisions = 30;
	[PGBrowsable]
	public int Init_RadialDivisions
	{
		get { return init_RadialDivisions; }
		set { init_RadialDivisions = value; }
	}
    protected double init_Amp = 1;
	[PGBrowsable]
	public double Init_Amp
	{
		get { return init_Amp; }
		set { init_Amp = value; }
	}
	[PGBrowsable]
	public PolarRT_ZFunc ZOfRTheta
	{
		get { return this.ZofR; }
		set { this.ZofR = value; }
	}
		/*
    private double init_tMax1 = 100;
    private double init_tMin1 = 0;
    private double init_rMin1 = 0;
    private double init_rMax1 = 100; 
    private double init_angleMin1 = 0;
    private double init_angleMax1 = 2 * Math.PI;
    private int init_angleDivisions1 = 20;
    private int init_radialDivisions1 = 20;
    private double init_mAmp1 = 1;
		*/
	public AnimatedPolarWaveform()
	{
		//CreateCircles();

		//if (this == null)
		//{
		//    this = new PolarWaveform(mDevice, mRenderManager, this.ZOfRTheta0, false);
		//}
		//mRenderManager.Register(this);

		//mOuterLimitsCircle = new Simple3dCircle(device, rendManager);
	}

	//private void CreateCircles()
	//{
	//    int circleCount = 10;
	//    if (circleCount > 0)
	//    {
	//        mCircleArray = new Simple3dCircle[circleCount];
	//        for (int i = 0; i < mCircleArray.Length; i++)
	//        {
	//            Simple3dCircle theCircle = new Simple3dCircle(mDevice, mRenderManager);
	//            theCircle.MainVertexColor = System.Drawing.Color.FromArgb(0, 255 / circleCount * i, 0);
	//            theCircle.Radius = (float)(2 * Math.PI * i);
	//            theCircle.CreateCircleOverXY();
	//            if (mCircleArray[i] != null)
	//                mCircleArray[i].UnregisterPrimitive();
	//            mCircleArray[i] = theCircle;
	//        }
	//    }

	//}
    public double ZOfRThetaMain(double radius, double theta)
    {
        if (this != null)
        {
            double fractionTDone = 1 - (radius - this.RMin) / (this.RMax - this.RMin);
            double t = fractionTDone * (this.TMax - this.TMin) + this.TMin;

            //double z = mSurface.Amplitude * Math.Cos(t);
            double sint = Math.Sin(t);
            double scale = 1 - fractionTDone * (1.0);
            double z = this.Amplitude * sint * (scale);// *cost + cost;
            return z;
        }
        else
        {
            return 0;
        }
    }
	public double ZOfRTheta1(double radius, double theta)
	{
		if (this != null)
		{
			double fractionTDone = 1 - (radius - this.RMin) / (this.RMax - this.RMin);
			double t = fractionTDone * (this.TMax - this.TMin) + this.TMin;

			//double z = mSurface.Amplitude * Math.Cos(t);
			double sint = Math.Sin(t);
			//double scale = 1 - fractionTDone * (1.0);
			double z = this.Amplitude * sint;// *cost + cost;
			return z;
		}
		else
		{
			return 0;
		}
	}

	protected bool mDoPreRender = true;
	[PGBrowsable]
	public bool PreRenderEnabled
	{
		get { return mDoPreRender; }
		set { mDoPreRender = value; }
	}

	protected bool mDoPostRender = true;
	[PGBrowsable]
	public bool PostRenderEnabled
	{
		get { return mDoPostRender; }
		set { mDoPostRender = value; }
	}

	public void PostRender() { }
    public void PreRender()
    {
		if (PreRenderEnabled == false)
			return;

        if (DoFrames())
        {
            //if (mSurface1 == null)
            //{
                //mSurface1 = new PolarWaveForm(mDevice, mRenderManager, this.ZOfRTheta1);
				//ResetValuestoTime0();
            //}
                
            //current options
			if (autoCalculateOptions)
				PreRender_SetDataOptions0();

			//if(drawOuterLimitsCircle)
			//{
			//    mOuterLimitsCircle.CreateCircleOverXY((float)this.RMax);
			//}

            /*
            mSurface.RMax += .125 * mDT;
            mSurface.RMin = mSurface.RMax - radialLength;
            double tmax = 2 * Math.PI;
            double tmin = -2 * Math.PI;
            mSurface.TMin = tmin;//-= .25 * mDT;
            mSurface.TMax = tmax;// Math.PI;
            mSurface.TMax += (.55) * mDT;
            mSurface.TMax +=.1*mDT;a
            mSurface.Amplitude = Amplitude; // - .1*(mTime);
            mWavePosition2d.X += (float)mDT * distancePerGeneration;
            */

            /*mSurface1.CreateVertexData(false);
            this.CreateVertexData(false);
            this.AddData(mSurface1);
            this.FlattenVertexData();
            this.UpdateDisplay();
             */
            this.CreateData();

        }

    }
    public void PreRender_SetDataOptions0()
    {
		double r0 = 4d;
        double t_grow_speed = .1;
        double maxTLength = 8d * Math.PI;
        double radialLength = 8d * Math.PI;

        double tmax = this.TMax + t_grow_speed;//Math.Min(this.TMax + speed, maxTLength);
        double tmin = 0;// Math.Max(this.TMin + speed, 0);
        double rmax = t_grow_speed * mTime + r0;

        /*
        double rmin; //0,
        if (rmax - radialLength > 0)
            rmin = Math.Min(rmax - radialLength, radialLength);
        else if (rmax - radialLength <= 0)
            rmin = 0;
        else
            rmin = 0;
        */
        double rmin = 0;

        this.TMax = tmax;
        this.TMin = 0;
        this.TMin = tmin;
        //tmax = Math.Min(tmax, Math.PI);
        ///mSurface.RMax += speed;
        this.RMax = rmax + init_RMax;
        this.RMin = init_RMin;

        double rFactor = 0;
        this.Amplitude = Amplitude - rFactor * Amplitude * (mTime / timeMaxToReset);

    }
	public void PreRender_SetDataOptions1()
	{
			
	}
	//protected void PreRender_SetDataOptions2()
	//{
	//    double speed = .1;
	//    double rFactor = .5;
	//    double maxTLength = 8d * Math.PI;
	//    double radialLength = 8d * Math.PI;

	//    double tmax = Math.Min(this.TMax + speed, maxTLength);
	//    double tmin = Math.Max(this.TMin + speed, 0);

	//    this.TMax = tmax;
	//    this.TMin = 0;
	//    this.TMin = tmin;
	//    //tmax = Math.Min(tmax, Math.PI);
	//    ///mSurface.RMax += speed;
	//    this.RMax = speed * mTime;
	//    this.RMin = Math.Max(speed * mTime - radialLength, 0);


	//    this.RMin += speed;
	//    this.Amplitude = Amplitude - rFactor * Amplitude * (mTime / timeMaxToReset);

	//}

	private void SaveCurrentValues()
	{
		init_TMax = this.TMax;
		init_TMin = this.TMin;
		init_RMin = this.RMin;
		init_RMax = this.RMax;
		init_AngleMin = this.AngleMin;
		init_AngleMax = this.AngleMax;
		init_AngleDivisions = this.AngleDivisions;
		init_RadialDivisions = this.RadialDivisions;
		init_Amp = this.Amplitude;
		mRestartTime = mTime;
	}
    public void ResetAnimated()
    {
        this.TMax = init_TMax;
        this.TMin = init_TMin;
        this.RMin = init_RMin; //try something greater than 0 as a start, when done set back to zero.
        this.RMax = init_RMax; //set to 10 now, when done set to a function of time.
        this.AngleMin = init_AngleMin;
        this.AngleMax =  init_AngleMax;
        this.AngleDivisions = init_AngleDivisions;
        this.RadialDivisions = init_RadialDivisions;
        this.Amplitude = init_Amp;

        /*mSurface1.TMax = init_tMax1;
        mSurface1.TMin = init_tMin1;
        mSurface1.RMin = init_rMin1; //try something greater than 0 as a start, when done set back to zero.
        mSurface1.RMax = init_rMax1; //set to 10 now, when done set to a function of time.
        mSurface1.AngleMin = init_angleMin1;
        mSurface1.AngleMax = init_angleMax1;
        mSurface1.AngleDivisions = init_angleDivisions1;
        mSurface1.RadialDivisions = init_radialDivisions1;
        mSurface1.Amplitude = init_mAmp1;      
		 */
    }
	private bool firstTime = true;
    private bool DoFrames()
    {
        bool recreateData = false;

		if (firstTime)
		{
			SaveCurrentValues();
			firstTime = false;
			recreateData = true;
		}

        if (mFramesSinceLastDataChange == mFramesPerChange)
        {
            if (mTime >= timeMaxToReset  || mTime == 0)
            {
                mTime = RestartTime;

                ResetAnimated();
            }
			mTime += mTimeScaleDelta;
            //important:
            mFramesSinceLastDataChange = 0;
            recreateData = true;

        }
        else
        {
        }
        mFramesSinceLastDataChange+=mFramesPerChange; 

        return recreateData;
    }
} //end of class
} //end of namespace
